﻿using System;
using System.Diagnostics;
using Hallenberg.Core;

namespace Hallenberg.SmartClient.Menu
{
    /// <summary>
    /// This attribute registeres a MenuItem in a the designated MenuManager.
    /// This attribute can be used in conjunction with access restriction attributes like [Authenticated], [Authorize] and the likes.
    /// When obtaining the menu items via the Menu Manager, depending on settings, menu items will be shown differently
    /// if they can not be executed.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes"), AttributeUsage(AttributeTargets.Method)]
    public class MenuItemAttribute : Attribute
    {
        public string MenuCollectionName { get; private set; }
        public string MenuItemName { get; private set; }
        public string MenuTitle { get; private set; }
        public IPredicate DisplayMenuEvaluator { get; private set; }
        public int SortIndex { get; set; }
        public string ToolTip { get; set; }
        public MenuItemDisabledPolicy DisabledPolicy { get; set; }
        public string ResourceMenuTitle { get; private set; }
        public Type ResourceType { get; private set; }

        public MenuItemAttribute(string menuCollectionName, Type resourceType, string resourceMenuTitle)
            : this(menuCollectionName)
        {
            Debug.Assert(resourceType != null);
            if (resourceType == null)
            {
                throw new ArgumentNullException("resourceType");
            }

            Debug.Assert(!string.IsNullOrEmpty(resourceMenuTitle));
            if (string.IsNullOrEmpty(resourceMenuTitle))
            {
                throw new ArgumentNullException("resourceMenuTitle");
            }

            this.ResourceType = resourceType;
            this.ResourceMenuTitle = resourceMenuTitle;
        }

        public MenuItemAttribute(string menuCollectionName, string menuItemName, string menuTitle)
            :this(menuCollectionName)
        {
            Debug.Assert(false == string.IsNullOrEmpty(menuItemName), "false == string.IsNullOrEmpty(menuItemName)");
            if (string.IsNullOrEmpty(menuItemName))
            {
                throw new ArgumentNullException("menuItemName");
            }

            Debug.Assert(false == string.IsNullOrEmpty(menuTitle), "false == string.IsNullOrEmpty(menuTitle)");
            if (string.IsNullOrEmpty(menuTitle))
            {
                throw new ArgumentNullException("menuTitle");
            }
            
            this.MenuItemName = menuItemName;
            this.MenuTitle = menuTitle;
        }

        private MenuItemAttribute(string menuCollectionName)
        {
            Debug.Assert(false == string.IsNullOrEmpty(menuCollectionName));
            if (string.IsNullOrEmpty(menuCollectionName))
            {
                throw new ArgumentNullException("menuCollectionName");
            }

            this.MenuCollectionName = menuCollectionName;
            this.SortIndex = 0;
            this.ToolTip = string.Empty;
            this.DisabledPolicy = MenuItemDisabledPolicy.Hide;
        }

        public MenuItemAttribute(string menuCollectionName, string menuItemName, string menuTitle, IPredicate displayMenuEvaluator)
            : this(menuCollectionName, menuItemName, menuTitle)
        {
            InitializeEvaluator(displayMenuEvaluator);
        }

        /// <summary>
        /// Initializes the evaluator.
        /// </summary>
        /// <param name="displayEvaluator">The display evaluator.</param>
        private void InitializeEvaluator(IPredicate displayEvaluator)
        {
            Debug.Assert(displayEvaluator != null);
            if (displayEvaluator == null)
            {
                throw new ArgumentNullException("displayEvaluator");
            }

            this.DisplayMenuEvaluator = displayEvaluator;
        }
    }
}
